home *** CD-ROM | disk | FTP | other *** search
/ GFX Sensations 1 / Graphic Sensations - Volume 1.iso / tools / amiga / 3d_tools / irit40s.lha / Irit / poly3d-r / poly3d-r.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-30  |  14.1 KB  |  412 lines

  1. /*****************************************************************************
  2. *   Program to draw 3D object as solid objects in GIF image file format.     *
  3. *                                         *
  4. * Options:                                     *
  5. * 1. -a ambient : Ratio of the ambient color.                     *
  6. * 2. -c n : Number of bit ber pixel (2^n is number of colors possible).         *
  7. * 3. -l x y z : Light source direction vector.                     *
  8. * 4. -2 : Force 2 light sources at opposite direction of light vectors.      *
  9. * 5. -m : More flag, to print more imformation on input/errors.             *
  10. * 6. -s x y : Specify new dimensions to generate the resulting image.         *
  11. * 7. -S SubSample : specifies dimension of pixel sub sampling (1..4).         *
  12. * 8. -g : Use gouraud shading.                             *
  13. * 9. -b : Delete Back facing polygons.                         *
  14. * 10. -M Mask : Create boolean Mask (coverage) image as well.             *
  15. * 11. -z : Print current version, and some helpfull data.             *
  16. * 12. -f FineNess : log based 2 of the surface to polygons subdiv, fineness. *
  17. *                                         *
  18. * Note some of those options may be permanently set to a different default   *
  19. * using the configuration file "Poly3D-R.cfg"                     *
  20. *                                         *
  21. * Usage: poly3d-r [-a Ambient] [-c N] [-l X Y Z] [-2] [-m] [-s Xsize Ysize]  *
  22. *               [-S SubSample] [-g] [-b] [-M Mask] [-z] [-f FineNess] DFiles *
  23. *                                         *
  24. * Written by:  Gershon Elber                Ver 3.0, Aug 1990    *
  25. *****************************************************************************/
  26.  
  27. #include <stdio.h>
  28. #include <math.h>
  29. #include <time.h>
  30. #include "program.h"
  31. #include "getarg.h"
  32. #include "genmat.h"
  33. #include "iritprsr.h"
  34. #include "config.h"
  35.  
  36. #ifdef __TURBOC__      /* Malloc debug routine - only on TC++ 1.0 and above. */
  37. #define __DEBUG_MALLOC__
  38. #endif /* __TURBOC__ */
  39.  
  40. #ifdef NO_CONCAT_STR
  41. static char *VersionStr =
  42.     "Poly3D-R    Version 4.0,    Gershon Elber,\n\
  43.     (C) Copyright 1989/90/91/92/93 Gershon Elber, Non commercial use only.";
  44. #else
  45. static char *VersionStr = "Poly3D-R    " VERSION ",    Gershon Elber,    "
  46.     __DATE__ ",  " __TIME__ "\n" COPYRIGHT ", Non commercial use only.";
  47. #endif /* NO_CONCAT_STR */
  48.  
  49. static char *CtrlStr =
  50. #ifdef DOUBLE
  51.     "poly3d-r a%-Ambient!F c%-N!d l%-X|Y|Z!F!F!F 2%- m%- s%-Xsize|Ysize!d!d S%-SubSample!d g%- b%- M%-Mask!s z%- f%-FineNess!d DFiles!*s";
  52. #else
  53.     "poly3d-r a%-Ambient!f c%-N!d l%-X|Y|Z!f!f!f 2%- m%- s%-Xsize|Ysize!d!d S%-SubSample!d g%- b%- M%-Mask!s z%- f%-FineNess!d DFiles!*s";
  54. #endif /* DOUBLE */
  55.  
  56. static long SaveTotalTime;
  57. static GifColorType MaskColorMap[2] = {     /* Boolean mask GIF file color map. */
  58.     {   0,   0,   0 },
  59.     { 255, 255, 255 }
  60. };
  61. /* Fineness surface subdivision control. */
  62. static int GlblFineNess = DEFAULT_FINENESS;
  63.  
  64. int GlblNumOfPolys = 0;         /* Total number of polygons scan converted. */
  65. int GlblNumOfVerts = 0;                /* Total number of vertices. */
  66. MatrixType GlblViewMat;                  /* Current view of object. */
  67.  
  68. /* Amount scene was scaled up from normalized [-1..1] size on both X & Y: */
  69. RealType GlblScaleUpFctr = 0.0;
  70.  
  71. /* The following are setable variables (via configuration file poly3d-h.cfg).*/
  72. int GlblMore = FALSE;
  73.  
  74. ShadeInfoStruct GlblShadeInfo = {
  75.     1,                           /* Sub samples per pixel. */
  76.     DEFAULT_BITS_PER_PIXEL,
  77.     0,
  78.     DEFAULT_COLOR,
  79.     DEFAULT_BACK_GROUND_COLOR,
  80.     FALSE,                        /* No two light sources. */
  81.     DEFAULT_SCREEN_XSIZE,
  82.     DEFAULT_SCREEN_YSIZE,
  83.     FALSE,                          /* No Gouraud shading. */
  84.     FALSE,                      /* No back facing deletion. */
  85.     NULL,
  86.     NULL,                        /* No color map yet. */
  87.     DEFAULT_LIGHT_SOURCE,
  88.     DEFAULT_AMBIENT,
  89.     DEFAULT_NORMAL_AVG_DEGREE
  90. };
  91.  
  92. static ConfigStruct SetUp[] = {
  93.   { "Ambient",        (VoidPtr) &GlblShadeInfo.Ambient,    SU_REAL_TYPE },
  94.   { "LightSrcX",    (VoidPtr) &GlblShadeInfo.LightSource[0],SU_REAL_TYPE },
  95.   { "LightSrcY",    (VoidPtr) &GlblShadeInfo.LightSource[1],SU_REAL_TYPE },
  96.   { "LightSrcZ",    (VoidPtr) &GlblShadeInfo.LightSource[2],SU_REAL_TYPE },
  97.   { "AvgDegree",    (VoidPtr) &GlblShadeInfo.NrmlAvgDegree,    SU_REAL_TYPE },
  98.   { "TwoSources",    (VoidPtr) &GlblShadeInfo.TwoSources,    SU_BOOLEAN_TYPE },
  99.   { "Gouraud",        (VoidPtr) &GlblShadeInfo.Gouraud,    SU_BOOLEAN_TYPE },
  100.   { "backFacing",    (VoidPtr) &GlblShadeInfo.BackFacing,    SU_BOOLEAN_TYPE },
  101.   { "SubSample",    (VoidPtr) &GlblShadeInfo.SubSamplePixel,SU_INTEGER_TYPE },
  102.   { "BitsPerPixel",    (VoidPtr) &GlblShadeInfo.BitsPerPixel,    SU_INTEGER_TYPE },
  103.   { "Color",        (VoidPtr) &GlblShadeInfo.DefaultColor,    SU_INTEGER_TYPE },
  104.   { "BackGroundColor",    (VoidPtr) &GlblShadeInfo.BackGroundColor,SU_INTEGER_TYPE },
  105.   { "Xsize",        (VoidPtr) &GlblShadeInfo.ScrnXSize,    SU_INTEGER_TYPE },
  106.   { "Ysize",        (VoidPtr) &GlblShadeInfo.ScrnYSize,    SU_INTEGER_TYPE },
  107.   { "FineNess",        (VoidPtr) &GlblFineNess,        SU_INTEGER_TYPE },
  108.   { "More",        (VoidPtr) &GlblMore,            SU_BOOLEAN_TYPE }
  109. };
  110. #define NUM_SET_UP    (sizeof(SetUp) / sizeof(ConfigStruct))
  111.  
  112. /* All polygons to be scan convert will be inserted into this hash table     */
  113. /* during the preprocessing (PrepareXXXX functions).                 */
  114. IPPolygonStruct **PolyHashTable;
  115.  
  116. static IPPolygonStruct *Surface2Polygons(CagdSrfStruct *Srf);
  117.  
  118. /*****************************************************************************
  119. * Main routine - Read Parameter    line and do what you need...             *
  120. *****************************************************************************/
  121. void main(int argc, char **argv)
  122. {
  123.     int AmbientFlag = FALSE,
  124.     ColorFlag = FALSE,
  125.     LightSrcFlag = FALSE,
  126.     GifMaskFlag = FALSE,
  127.     VerFlag = FALSE,
  128.     NumFiles = 0,
  129.     ImageSizeFlag = FALSE,
  130.     SubSampleFlag = FALSE,
  131.     FineNessFlag = FALSE,
  132.     Error;
  133.     char *GifMaskName,
  134.     **FileNames = NULL;
  135.     RealType Size, Scale;
  136.     MatrixType Mat;
  137.     IPObjectStruct *PObjects;
  138.     GifFileType *GifFile,
  139.     *GifMask = NULL;
  140.  
  141.     SaveTotalTime = time(NULL);                  /* Save starting time. */
  142.  
  143.     Config("poly3d-r", SetUp, NUM_SET_UP);   /* Read config. file if exists. */
  144.  
  145.     if ((Error = GAGetArgs (argc, argv, CtrlStr,
  146.         &AmbientFlag, &GlblShadeInfo.Ambient,
  147.         &ColorFlag, &GlblShadeInfo.BitsPerPixel, &LightSrcFlag,
  148.         &GlblShadeInfo.LightSource[0],
  149.         &GlblShadeInfo.LightSource[1],
  150.         &GlblShadeInfo.LightSource[2],
  151.         &GlblShadeInfo.TwoSources, &GlblMore, &ImageSizeFlag,
  152.         &GlblShadeInfo.ScrnXSize, &GlblShadeInfo.ScrnYSize,
  153.         &SubSampleFlag, &GlblShadeInfo.SubSamplePixel,
  154.         &GlblShadeInfo.Gouraud, &GlblShadeInfo.BackFacing,
  155.         &GifMaskFlag, &GifMaskName,
  156.         &VerFlag, &FineNessFlag, &GlblFineNess,
  157.         &NumFiles, &FileNames)) != 0) {
  158.     GAPrintErrMsg(Error);
  159.     GAPrintHowTo(CtrlStr);
  160.     Poly3drExit(1);
  161.     }
  162.  
  163.     if (GlblShadeInfo.Ambient < 0.0 || GlblShadeInfo.Ambient > 1.0) {
  164.     fprintf(stderr,
  165.             "Ambient light specified not in [0.0..1.0] range, %lf selected instead.\n",
  166.         DEFAULT_AMBIENT);
  167.     GlblShadeInfo.Ambient = DEFAULT_AMBIENT;
  168.     }
  169.     if (GlblShadeInfo.BitsPerPixel < 1 || GlblShadeInfo.BitsPerPixel > 8) {
  170.     fprintf(stderr,
  171.             "PitsPerPixel not in [1..8] range, %d selected instead.\n",
  172.         DEFAULT_BITS_PER_PIXEL);
  173.     GlblShadeInfo.BitsPerPixel = DEFAULT_BITS_PER_PIXEL;
  174.     }
  175.  
  176.     Size = sqrt(SQR(GlblShadeInfo.LightSource[0]) +
  177.         SQR(GlblShadeInfo.LightSource[1]) +
  178.         SQR(GlblShadeInfo.LightSource[2]));
  179.     if (ABS(Size) < EPSILON) {
  180.     fprintf(stderr, "Light source vector is zero, Z axis selected instead.\n");
  181.     GlblShadeInfo.LightSource[0] =
  182.     GlblShadeInfo.LightSource[1] = 0.0;
  183.     GlblShadeInfo.LightSource[2] = 1.0;
  184.     }
  185.     else {
  186.     GlblShadeInfo.LightSource[0] /= Size;
  187.     GlblShadeInfo.LightSource[1] /= Size;
  188.     GlblShadeInfo.LightSource[2] /= Size;
  189.     }
  190.  
  191.     if (VerFlag) {
  192.     fprintf(stderr, "\n%s\n\n", VersionStr);
  193.     GAPrintHowTo(CtrlStr);
  194.     ConfigPrint(SetUp, NUM_SET_UP);
  195.     Poly3drExit(0);
  196.     }
  197.  
  198.     if (!NumFiles) {
  199.     fprintf(stderr, "No data file names were given, exit.\n");
  200.     GAPrintHowTo(CtrlStr);
  201.     Poly3drExit(1);
  202.     }
  203.  
  204.     if (SubSampleFlag) {
  205.     if (GlblShadeInfo.SubSamplePixel < 1 || GlblShadeInfo.SubSamplePixel > 4) {
  206.         fprintf(stderr, "Sub sampling can be 1 to 4 only (1x1 to 4x4).\n");
  207.         GAPrintHowTo(CtrlStr);
  208.         Poly3drExit(1);
  209.     }
  210.     }
  211.  
  212.     /* Get the data files: */
  213.     if ((PObjects = IritPrsrGetDataFiles(FileNames, NumFiles, TRUE,
  214.                      GlblMore)) == NULL)
  215.     Poly3drExit(1);
  216.  
  217.     /* Compute the viewing matrices and related data: */
  218.     if (IritPrsrWasPrspMat)
  219.     MatMultTwo4by4(GlblViewMat, IritPrsrViewMat, IritPrsrPrspMat);
  220.     else
  221.     GEN_COPY(GlblViewMat, IritPrsrViewMat, sizeof(MatrixType));
  222.  
  223.     /* Now its time to scale the normalized image (+/-1 on both X & Y) to    */
  224.     /* size specified by the image dimensions. We scale up to the SMALLER    */
  225.     /* dimension, and put the center at the image center.             */
  226.     /* Also, as the GIF image starts at the top, we must flip the image      */
  227.     /* along Y axis.                                 */
  228.     GlblScaleUpFctr = Scale = MIN(GlblShadeInfo.ScrnXSize *
  229.                   GlblShadeInfo.SubSamplePixel,
  230.                   GlblShadeInfo.ScrnYSize *
  231.                   GlblShadeInfo.SubSamplePixel) / 2.0;
  232.     MatGenMatScale(Scale, -Scale, Scale, Mat);
  233.     MatMultTwo4by4(GlblViewMat, GlblViewMat, Mat);
  234.     MatGenMatTrans(GlblShadeInfo.ScrnXSize * GlblShadeInfo.SubSamplePixel / 2.0,
  235.            GlblShadeInfo.ScrnYSize * GlblShadeInfo.SubSamplePixel / 2.0,
  236.            0.0, Mat);
  237.     MatMultTwo4by4(GlblViewMat, GlblViewMat, Mat);
  238.  
  239.     /* Prepare data structures of objects themselves: */
  240.     PrepareViewData(PObjects);
  241.  
  242.     /* Into shadingInfo global structure: */
  243.     PrepareColorTable(PObjects);
  244.  
  245.     EvalVrtxColors(PObjects);
  246.  
  247. #ifndef DEBUG_NO_GIF
  248.  
  249.     /* Open stdout for the GIF image file: */
  250.     if ((GifFile = EGifOpenFileHandle(1)) == NULL ||
  251.     EGifPutScreenDesc(GifFile,
  252.         GlblShadeInfo.ScrnXSize, GlblShadeInfo.ScrnYSize,
  253.         GlblShadeInfo.BitsPerPixel, 0,
  254.         GlblShadeInfo.BitsPerPixel, GlblShadeInfo.PColorMap) ==
  255.                                 GIF_ERROR ||
  256.     EGifPutImageDesc(GifFile,
  257.         0, 0, GlblShadeInfo.ScrnXSize, GlblShadeInfo.ScrnYSize, FALSE,
  258.         GlblShadeInfo.BitsPerPixel, NULL) == GIF_ERROR)
  259.     QuitGifError();
  260.     /* Open special mask file if required: */
  261.     if (GifMaskFlag &&
  262.     ((GifMask = EGifOpenFileName(GifMaskName, FALSE)) == NULL ||
  263.      EGifPutScreenDesc(GifMask,
  264.                GlblShadeInfo.ScrnXSize, GlblShadeInfo.ScrnYSize,
  265.                1, 0, 1, MaskColorMap) == GIF_ERROR ||
  266.      EGifPutImageDesc(GifMask, 0, 0,
  267.               GlblShadeInfo.ScrnXSize, GlblShadeInfo.ScrnYSize,
  268.               FALSE, 1, NULL) == GIF_ERROR))
  269.     QuitGifError();
  270.  
  271. #endif /* DEBUG_NO_GIF */
  272.  
  273.     ScanConvertData(GifFile, GifMask);     /* Do the real interesting stuff... */
  274.  
  275. #ifndef DEBUG_NO_GIF
  276.  
  277.     EGifCloseFile(GifFile);
  278.     if (GifMask)
  279.     EGifCloseFile(GifMask);
  280.  
  281. #endif /* DEBUG_NO_GIF */
  282.  
  283.     Poly3drExit(0);
  284. }
  285.  
  286. /*****************************************************************************
  287. * Routine to convert all surfaces/curves into polylines as follows:         *
  288. * Curves are converted to single polyline with SamplesPerCurve samples.         *
  289. * Surface are converted into GlblNumOfIsolines curves in each axes, each     *
  290. * handled as Curves above. The curves and surfaces are then deleted.         *
  291. *****************************************************************************/
  292. IPObjectStruct *IritPrsrProcessFreeForm(IPObjectStruct *CrvObjs,
  293.                     IPObjectStruct *SrfObjs)
  294. {
  295.     CagdCrvStruct *Crvs;
  296.     CagdSrfStruct *Srf, *Srfs;
  297.     IPObjectStruct *PObj, *PObjNext;
  298.     IPPolygonStruct *PPolygon, *PPolygonTemp;
  299.  
  300.     if (CrvObjs == NULL && SrfObjs == NULL)
  301.     return NULL;
  302.  
  303.     /* Make sure requested format is something reasonable. */
  304.     if (GlblFineNess < 2) {
  305.     GlblFineNess = 2;
  306.     if (GlblMore)
  307.         fprintf(stderr, "FineNess is less than 2, 2 picked instead.\n");
  308.     }
  309.  
  310.     if (CrvObjs) {
  311.     /* Curves are not rendered at this time and they are ignored. */
  312.     for (PObj = CrvObjs; PObj != NULL;) {
  313.         Crvs = PObj -> U.Crvs;
  314.         CagdCrvFreeList(Crvs);
  315.         PObjNext = PObj -> Pnext;
  316.         IPFreeObject(PObj);
  317.         PObj = PObjNext;
  318.     }
  319.     CrvObjs = NULL;
  320.     }
  321.  
  322.     if (SrfObjs) {
  323.     for (PObj = SrfObjs; PObj != NULL; PObj = PObj -> Pnext) {
  324.         Srfs = PObj -> U.Srfs;
  325.         PObj -> U.Pl = NULL;
  326.         PObj -> ObjType = IP_OBJ_POLY;
  327.         IP_SET_POLYGON_OBJ(PObj);
  328.  
  329.         for (Srf = Srfs; Srf != NULL; Srf = Srf -> Pnext) {
  330.         PPolygon = PPolygonTemp = Surface2Polygons(Srf);
  331.         while (PPolygonTemp -> Pnext)
  332.             PPolygonTemp = PPolygonTemp -> Pnext;
  333.         PPolygonTemp -> Pnext = PObj -> U.Pl;
  334.         PObj -> U.Pl = PPolygon;
  335.         }
  336.         CagdSrfFreeList(Srfs);
  337.     }
  338.     }
  339.  
  340.     return SrfObjs;
  341. }
  342.  
  343. /*****************************************************************************
  344. * Routine to convert a single surface into a polygons with GlblFineNess      *
  345. * samples as the subdivision fineness measure.                     *
  346. *****************************************************************************/
  347. static IPPolygonStruct *Surface2Polygons(CagdSrfStruct *Srf)
  348. {
  349.     int i, j;
  350.     IPVertexStruct *V, *VHead;
  351.     IPPolygonStruct *P,
  352.     *PHead = NULL;
  353.     CagdPolygonStruct *CagdPolygon,
  354.     *CagdPolygonHead = NULL;
  355.  
  356.     CagdPolygonHead = CagdSrf2Polygons(Srf, 1 << GlblFineNess, TRUE, TRUE,
  357.                                        FALSE);
  358.  
  359.     for (CagdPolygon = CagdPolygonHead;
  360.      CagdPolygon != NULL;
  361.      CagdPolygon = CagdPolygon -> Pnext) {
  362.     /* All polygons are triangles! */
  363.  
  364.     for (i = 0, VHead = NULL; i < 3; i++) {         /* Convert to vertices. */
  365.         if (VHead == NULL)
  366.         VHead = V = IPAllocVertex(0, 0, NULL, NULL);
  367.         else {
  368.         V -> Pnext = IPAllocVertex(0, 0, NULL, NULL);
  369.         V = V -> Pnext;
  370.         }
  371.         IP_SET_NORMAL_VRTX(V);               /* Vertex has normal. */
  372.  
  373.         for (j = 0; j < 3; j++)                /* Convert to our format. */
  374.         V -> Coord[j] = CagdPolygon -> Polygon[i].Pt[j];
  375.         for (j = 0; j < 3; j++)
  376.         V -> Normal[j] = CagdPolygon -> Normal[i].Vec[j];
  377.  
  378.     }
  379.  
  380.     P = IPAllocPolygon(0, 0, VHead, PHead);
  381.     PHead = P;
  382.     }
  383.  
  384.     CagdPolygonFreeList(CagdPolygonHead);
  385.  
  386.     return PHead;
  387. }
  388.  
  389. /*****************************************************************************
  390. * Poly3d-r Exit routine. Note it might call to CloseGraph without calling    *
  391. * InitGraph(), or call MouseClose() without MouseInit(), or call         *
  392. * RestoreCtrlBrk() without SetUpCtrlBrk() and it is the responsibility         *
  393. * of the individual modules to do nothing in these cases.             *
  394. *****************************************************************************/
  395. void Poly3drExit(int ExitCode)
  396. {
  397.     fprintf(stderr,
  398.     "\nPoly3D-R: Total RealTime %ld seconds.\n",
  399.         time(NULL) - SaveTotalTime);
  400.  
  401.     exit(ExitCode);
  402. }
  403.  
  404. /******************************************************************************
  405. * Close output file (if open), and exit.                      *
  406. ******************************************************************************/
  407. void QuitGifError(void)
  408. {
  409.     PrintGifError();
  410.     Poly3drExit('G');
  411. }
  412.